package com.abc.recycling.service.impl;

import com.abc.recycling.mapper.OrderMapper;
import com.abc.recycling.model.Order;
import com.abc.recycling.repository.OrderRepository;
import com.abc.recycling.service.OrderService;
import com.abc.recycling.service.EvaluationService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.PageImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.ArrayList;
import java.math.BigDecimal;
import java.util.Optional;
import java.util.HashMap;
import java.util.Collections;
import java.util.Arrays;

@Slf4j
@Service
@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService {

    private final OrderRepository orderRepository;
    private final EvaluationService evaluationService;
    private final OrderMapper orderMapper;

    @Override
    public Order getOrderById(Long id) {
        try {
            log.debug("获取订单信息, id={}", id);
            return orderRepository.findById(id).orElse(null);
        } catch (Exception e) {
            log.error("获取订单信息失败: {}", e.getMessage());
            throw e;
        }
    }

    @Override
    public List<Order> getAllOrders() {
        try {
            log.debug("获取所有订单");
            return orderRepository.findAll();
        } catch (Exception e) {
            log.error("获取所有订单失败: {}", e.getMessage());
            throw e;
        }
    }

    @Override
    public List<Order> getOrdersByUserId(Long userId) {
        try {
            log.debug("获取用户订单列表, userId={}", userId);
            List<Order> orders = orderRepository.findByUserId(userId);
            log.debug("获取到{}条订单记录", orders.size());
            orders.forEach(order -> {
                log.debug("订单详情: id={}, orderNo={}, userName={}, userRealName={}, collectorName={}, collectorRealName={}", 
                    order.getId(), order.getOrderNo(), 
                    order.getDebugUserUsername(), order.getDebugUserRealname(),
                    order.getDebugCollectorUsername(), order.getDebugCollectorRealname());
            });
            return orders;
        } catch (Exception e) {
            log.error("获取用户订单列表失败: {}", e.getMessage());
            throw e;
        }
    }

    @Override
    public List<Order> getOrdersByCollectorId(Long collectorId) {
        try {
            log.debug("获取回收员订单列表, collectorId={}", collectorId);
            List<Order> orders = orderRepository.findByCollectorId(collectorId);
            log.debug("获取到{}条订单记录", orders.size());
            orders.forEach(order -> {
                log.debug("订单详情: id={}, orderNo={}, userName={}, userRealName={}, collectorName={}, collectorRealName={}", 
                    order.getId(), order.getOrderNo(), 
                    order.getDebugUserUsername(), order.getDebugUserRealname(),
                    order.getDebugCollectorUsername(), order.getDebugCollectorRealname());
            });
            return orders;
        } catch (Exception e) {
            log.error("获取回收员订单列表失败: {}", e.getMessage());
            throw e;
        }
    }

    @Override
    public Page<Order> getOrdersByUserIdPaged(Long userId, Pageable pageable) {
        try {
            log.debug("获取用户订单分页列表, userId={}, page={}, size={}", 
                    userId, pageable.getPageNumber(), pageable.getPageSize());
            return orderRepository.findByUserId(userId, pageable);
        } catch (Exception e) {
            log.error("获取用户订单分页列表失败: {}", e.getMessage());
            throw e;
        }
    }

    @Override
    @Transactional
    public Order createOrder(Order order) {
        try {
            log.info("创建新订单");
            order.setOrderNo(generateOrderNo());
            order.setStatus("PENDING");
            order.setCreateTime(LocalDateTime.now());
            order.setUpdateTime(LocalDateTime.now());
            Order savedOrder = orderRepository.save(order);
            log.info("订单创建成功, orderNo={}", savedOrder.getOrderNo());
            return savedOrder;
        } catch (Exception e) {
            log.error("创建订单失败: {}", e.getMessage());
            throw e;
        }
    }

    @Override
    @Transactional
    public Order updateOrder(Order order) {
        try {
            log.info("更新订单信息, orderId={}", order.getId());
            order.setUpdateTime(LocalDateTime.now());
            Order updatedOrder = orderRepository.save(order);
            log.info("订单更新成功");
            return updatedOrder;
        } catch (Exception e) {
            log.error("更新订单失败: {}", e.getMessage());
            throw e;
        }
    }

    @Override
    public void deleteOrder(Long id) {
        try {
            log.info("删除订单, orderId={}", id);
            orderRepository.deleteById(id);
            log.info("订单删除成功");
        } catch (Exception e) {
            log.error("删除订单失败: {}", e.getMessage());
            throw e;
        }
    }

    @Override
    @Transactional
    public void rateOrder(Long orderId, Integer rating, String comment) {
        try {
            log.info("评价订单, orderId={}, rating={}", orderId, rating);
            Optional<Order> orderOpt = orderRepository.findById(orderId);
            if (orderOpt.isPresent()) {
                Order order = orderOpt.get();
                order.setRating(rating);
                order.setComment(comment);
                order.setUpdateTime(LocalDateTime.now());
                orderRepository.save(order);
                log.info("订单评价成功");
            } else {
                log.warn("订单不存在, orderId={}", orderId);
            }
        } catch (Exception e) {
            log.error("评价订单失败: {}", e.getMessage());
            throw e;
        }
    }

    @Override
    public Long countOrdersByStatus(String status) {
        try {
            log.debug("统计订单数量, status={}", status);
            return orderRepository.countByStatus(status);
        } catch (Exception e) {
            log.error("统计订单数量失败: {}", e.getMessage());
            throw e;
        }
    }

    @Override
    public List<Map<String, Object>> getOrderTrendData() {
        try {
            log.debug("获取订单趋势数据");
            return orderRepository.getOrderTrend(LocalDateTime.now().minusMonths(6));
        } catch (Exception e) {
            log.error("获取订单趋势数据失败: {}", e.getMessage());
            throw e;
        }
    }

    @Override
    public List<Map<String, Object>> getItemDistributionData() {
        try {
            log.debug("获取物品分布数据");
            return orderRepository.getItemDistribution();
        } catch (Exception e) {
            log.error("获取物品分布数据失败: {}", e.getMessage());
            throw e;
        }
    }

    @Override
    public Long countActiveUsers() {
        try {
            log.debug("统计活跃用户数");
            return orderRepository.countActiveUsers();
        } catch (Exception e) {
            log.error("统计活跃用户数失败: {}", e.getMessage());
            throw e;
        }
    }

    @Override
    public Double getTotalWeight() {
        try {
            log.debug("获取总回收重量");
            return orderRepository.sumTotalWeight();
        } catch (Exception e) {
            log.error("获取总回收重量失败: {}", e.getMessage());
            throw e;
        }
    }

    @Override
    public Double getTotalIncome() {
        try {
            log.debug("获取总收入");
            return orderRepository.getTotalIncome();
        } catch (Exception e) {
            log.error("获取总收入失败: {}", e.getMessage());
            throw e;
        }
    }

    @Override
    public List<Order> findRecentOrdersByUser(Long userId) {
        try {
            log.debug("获取用户最近订单, userId={}", userId);
            return orderRepository.findByUserIdOrderByCreateTimeDesc(userId);
        } catch (Exception e) {
            log.error("获取用户最近订单失败: {}", e.getMessage());
            throw e;
        }
    }

    @Override
    public List<Order> getRecentOrders(int limit) {
        try {
            log.debug("获取最近订单, limit={}", limit);
            return orderRepository.findTopNByOrderByCreateTimeDesc(PageRequest.of(0, limit));
        } catch (Exception e) {
            log.error("获取最近订单失败: {}", e.getMessage());
            throw e;
        }
    }

    @Override
    @Transactional
    public void updateOrderStatus(Long orderId, String status) {
        try {
            log.info("更新订单状态, orderId={}, status={}", orderId, status);
            Optional<Order> orderOpt = orderRepository.findById(orderId);
            if (orderOpt.isPresent()) {
                Order order = orderOpt.get();
                order.setStatus(status);
                if ("COMPLETED".equals(status)) {
                    order.setCompleteTime(LocalDateTime.now());
                }
                order.setUpdateTime(LocalDateTime.now());
                orderRepository.save(order);
                log.info("订单状态更新成功");
            } else {
                log.warn("订单不存在, orderId={}", orderId);
            }
        } catch (Exception e) {
            log.error("更新订单状态失败: {}", e.getMessage());
            throw e;
        }
    }

    @Override
    public Long countTodayOrders() {
        try {
            log.debug("统计今日订单数");
            LocalDateTime startOfDay = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0);
            LocalDateTime endOfDay = startOfDay.plusDays(1);
            return orderRepository.countByCreateTimeBetween(startOfDay, endOfDay);
        } catch (Exception e) {
            log.error("统计今日订单数失败: {}", e.getMessage());
            throw e;
        }
    }

    @Override
    public Double getTodayTotalWeight() {
        try {
            log.debug("获取今日总回收重量");
            LocalDateTime startOfDay = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0);
            LocalDateTime endOfDay = startOfDay.plusDays(1);
            return orderRepository.sumWeightByDateRange(startOfDay, endOfDay);
        } catch (Exception e) {
            log.error("获取今日总回收重量失败: {}", e.getMessage());
            throw e;
        }
    }

    private String generateOrderNo() {
        LocalDateTime now = LocalDateTime.now();
        String timestamp = String.format("%tY%tm%td%tH%tM%tS", now, now, now, now, now, now);
        String random = String.format("%04d", new Random().nextInt(10000));
        return timestamp + random;
    }

    @Override
    public List<Map<String, Object>> getMonthlyOrderCount(int months) {
        try {
            log.debug("获取月度订单统计, months={}", months);
            LocalDateTime endTime = LocalDateTime.now();
            LocalDateTime startTime = endTime.minusMonths(months);
            return orderRepository.getMonthlyOrderCount(startTime, endTime);
        } catch (Exception e) {
            log.error("获取月度订单统计失败: {}", e.getMessage());
            throw e;
        }
    }

    @Override
    public List<Map<String, Object>> getItemDistribution(LocalDateTime startTime, LocalDateTime endTime) {
        try {
            log.debug("获取物品分布数据, startTime={}, endTime={}", startTime, endTime);
            return orderRepository.getItemDistributionByDateRange(startTime, endTime);
        } catch (Exception e) {
            log.error("获取物品分布数据失败: {}", e.getMessage());
            throw e;
        }
    }

    @Override
    public Page<Order> findAll(Pageable pageable) {
        return orderRepository.findAll(pageable);
    }

    @Override
    public Page<Order> findByStatus(String status, Pageable pageable) {
        try {
            log.debug("根据状态查询订单, status={}", status);
            return orderRepository.findByStatus(status, pageable);
        } catch (Exception e) {
            log.error("根据状态查询订单失败: {}", e.getMessage());
            throw e;
        }
    }

    @Override
    public Page<Order> findByKeyword(String keyword, Pageable pageable) {
        try {
            log.debug("根据关键字查询订单, keyword={}", keyword);
            return orderRepository.findByKeyword(keyword, pageable);
        } catch (Exception e) {
            log.error("根据关键字查询订单失败: {}", e.getMessage());
            throw e;
        }
    }

    @Override
    public Page<Order> findByStatusAndKeyword(String status, String keyword, Pageable pageable) {
        try {
            log.debug("根据状态和关键字查询订单, status={}, keyword={}", status, keyword);
            return orderRepository.findByStatusAndKeyword(status, keyword, pageable);
        } catch (Exception e) {
            log.error("根据状态和关键字查询订单失败: {}", e.getMessage());
            throw e;
        }
    }

    @Override
    @Transactional
    public void cancelOrder(Long orderId) {
        try {
            log.info("取消订单, orderId={}", orderId);
            updateOrderStatus(orderId, "CANCELLED");
            log.info("订单取消成功");
        } catch (Exception e) {
            log.error("取消订单失败: {}", e.getMessage());
            throw e;
        }
    }

    @Override
    public void exportOrders(String filePath, LocalDateTime startTime, LocalDateTime endTime) {
        try {
            log.info("导出订单数据, filePath={}, startTime={}, endTime={}", filePath, startTime, endTime);
            List<Order> orders = orderRepository.findByCreateTimeBetween(startTime, endTime);
            // 导出逻辑...
            log.info("订单数据导出成功");
        } catch (Exception e) {
            log.error("导出订单数据失败: {}", e.getMessage());
            throw e;
        }
    }

    @Override
    public Page<Order> findOrders(String keyword, String status, Pageable pageable) {
        try {
            log.debug("开始搜索订单, keyword={}, status={}, page={}, size={}", 
                    keyword, status, pageable.getPageNumber(), pageable.getPageSize());
            
            // 使用findAllOrdersWithUserInfo方法获取订单信息
            Page<Order> result = findAllOrdersWithUserInfo(pageable);
            
            if (result != null && result.hasContent()) {
                for (Order order : result.getContent()) {
                    log.debug("订单数据: orderNo={}, userId={}, userName={}, userRealName={}, " +
                            "collectorId={}, collectorName={}, collectorRealName={}, price={}",
                            order.getOrderNo(), order.getUserId(), 
                            order.getUserName(), order.getUserRealName(),
                            order.getCollectorId(), order.getCollectorName(), 
                            order.getCollectorRealName(), order.getPrice());
                }
            } else {
                log.debug("未找到订单数据");
            }
            
            return result;
        } catch (Exception e) {
            log.error("搜索订单失败: {}", e.getMessage(), e);
            throw e;
        }
    }

    @Override
    public List<Order> findOrders(String keyword, String status) {
        try {
            log.debug("开始搜索订单列表, keyword={}, status={}", keyword, status);
            List<Order> result;
            if (status != null && !status.isEmpty()) {
                result = orderRepository.findByStatusAndOrderNoContaining(status, keyword, 
                    PageRequest.of(0, Integer.MAX_VALUE)).getContent();
            } else {
                result = orderRepository.findByOrderNoContaining(keyword, 
                    PageRequest.of(0, Integer.MAX_VALUE)).getContent();
            }
            
            if (result != null && !result.isEmpty()) {
                for (Order order : result) {
                    log.debug("订单数据: orderNo={}, userId={}, userName={}, collectorId={}, collectorName={}, price={}",
                            order.getOrderNo(), order.getUserId(), order.getUserName(), 
                            order.getCollectorId(), order.getCollectorName(), order.getPrice());
                }
            } else {
                log.debug("未找到订单数据");
            }
            
            return result;
        } catch (Exception e) {
            log.error("搜索订单列表失败: {}", e.getMessage(), e);
            throw e;
        }
    }

    @Override
    public Page<Order> searchOrders(String keyword, String status, Pageable pageable) {
        return findOrders(keyword, status, pageable);
    }

    @Override
    public Double getTotalWeightByStatus(String status) {
        try {
            log.debug("获取指定状态的总重量, status={}", status);
            return orderRepository.sumWeightByStatus(status);
        } catch (Exception e) {
            log.error("获取指定状态的总重量失败: {}", e.getMessage());
            throw e;
        }
    }

    @Override
    public Double getAverageRating() {
        try {
            log.debug("获取平均评分");
            return orderRepository.averageRating();
        } catch (Exception e) {
            log.error("获取平均评分失败: {}", e.getMessage());
            throw e;
        }
    }

    @Override
    public Long countOrdersByUser(Long userId) {
        try {
            log.debug("统计用户订单数量, userId={}", userId);
            return orderRepository.countByUserId(userId);
        } catch (Exception e) {
            log.error("统计用户订单数量失败: {}", e.getMessage());
            throw e;
        }
    }

    @Override
    public BigDecimal getTotalWeightByUser(Long userId) {
        try {
            log.debug("获取用户总回收重量, userId={}", userId);
            Double weight = orderRepository.sumWeightByUserId(userId);
            return weight != null ? BigDecimal.valueOf(weight) : BigDecimal.ZERO;
        } catch (Exception e) {
            log.error("获取用户总回收重量失败: {}", e.getMessage());
            throw e;
        }
    }

    @Override
    public Double getAverageRatingByUser(Long userId) {
        Double rating = orderRepository.averageRatingByUserId(userId);
        return rating != null ? rating : 0.0;
    }

    @Override
    public BigDecimal getTotalIncomeByUser(Long userId) {
        Double income = orderRepository.sumIncomeByUserId(userId);
        return income != null ? new BigDecimal(income.toString()) : BigDecimal.ZERO;
    }

    @Override
    @Transactional
    public void updateOrderRating(Long orderId, Integer rating, String comment) {
        rateOrder(orderId, rating, comment);
    }

    @Override
    public Order findById(Long orderId) {
        return getOrderById(orderId);
    }

    @Override
    public List<Map<String, Object>> getCollectorOrderStats(Long collectorId) {
        Map<String, Object> stats = orderRepository.getCollectorOrderStats(collectorId);
        return stats != null ? Arrays.asList(stats) : new ArrayList<>();
    }

    @Override
    public Page<Order> findByCollectorId(Long collectorId, Pageable pageable) {
        return orderRepository.findByCollectorId(collectorId, pageable);
    }

    @Override
    public List<Order> findByCollectorId(Long collectorId) {
        return orderRepository.findByCollectorId(collectorId);
    }

    @Override
    public List<Map<String, Object>> getOrderTrendByCollector(Long collectorId, LocalDateTime startTime, LocalDateTime endTime) {
        return orderRepository.getOrderTrendByCollector(collectorId, startTime, endTime);
    }

    @Override
    public List<Map<String, Object>> getItemDistributionByCollector(Long collectorId) {
        return orderRepository.getItemDistributionByCollector(collectorId);
    }

    @Override
    public Long countOrdersByDate(LocalDateTime date) {
        LocalDateTime startOfDay = date.withHour(0).withMinute(0).withSecond(0);
        LocalDateTime endOfDay = startOfDay.plusDays(1);
        return orderRepository.countByCreateTimeBetween(startOfDay, endOfDay);
    }

    @Override
    public List<Map<String, Object>> getOrderTrend(LocalDateTime startTime) {
        return orderRepository.getOrderTrend(startTime);
    }

    @Override
    public List<Map<String, Object>> getItemDistribution() {
        return orderRepository.getItemDistribution();
    }

    @Override
    public Map<String, Object> getOrderStats() {
        Map<String, Object> stats = new HashMap<>();
        stats.put("totalOrders", orderRepository.count());
        stats.put("totalWeight", orderRepository.sumTotalWeight());
        stats.put("totalIncome", orderRepository.getTotalIncome());
        stats.put("averageRating", orderRepository.averageRating());
        return stats;
    }

    @Override
    public List<Order> getOrdersByDateRange(LocalDateTime startTime, LocalDateTime endTime) {
        return orderRepository.findByCreateTimeBetween(startTime, endTime);
    }

    @Override
    public Page<Order> findByOrderNo(String orderNo, Pageable pageable) {
        try {
            log.debug("根据订单号查询订单, orderNo={}", orderNo);
            return orderRepository.findByOrderNoContaining(orderNo, pageable);
        } catch (Exception e) {
            log.error("根据订单号查询订单失败: {}", e.getMessage());
            throw e;
        }
    }

    @Override
    public Page<Order> findAllOrdersWithUserInfo(Pageable pageable) {
        try {
            log.info("开始查询订单列表，分页参数：{}", pageable);
            List<Order> orders = orderMapper.findAllWithUserInfo(pageable);
            long total = orderMapper.countAllWithUserInfo();
            log.info("查询到{}条订单记录，总记录数：{}", orders.size(), total);
            
            for (Order order : orders) {
                log.info("订单ID: {}", order.getId());
                log.info("用户信息 - ID: {}, 用户名: {}, 真实姓名: {}", 
                    order.getUserId(), order.getUserName(), order.getUserRealName());
                log.info("回收员信息 - ID: {}, 用户名: {}, 真实姓名: {}", 
                    order.getCollectorId(), order.getCollectorName(), order.getCollectorRealName());
                log.info("调试信息 - 用户ID: {}, 用户名: {}, 真实姓名: {}", 
                    order.getDebugUserId(), order.getDebugUserUsername(), order.getDebugUserRealname());
                log.info("调试信息 - 回收员ID: {}, 用户名: {}, 真实姓名: {}", 
                    order.getDebugCollectorId(), order.getDebugCollectorUsername(), order.getDebugCollectorRealname());
            }
            
            return new PageImpl<>(orders, pageable, total);
        } catch (Exception e) {
            log.error("查询订单列表失败: {}", e.getMessage(), e);
            throw e;
        }
    }
}